using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;
using Perovich.GameObjects;
using Perovich.GameObjects.Helpers;
using Perovich.GameObjects.TwoDimensional;
using Perovich.GameObjects.Controls;
using Perovich.GameObjects.TwoDimensional.Particles;
using System.Diagnostics;
using Perovich.GameObjects.Interfaces;
#if XBOX
#else
using System.Windows;
using Perovich.GameObjects.Entities;
using Perovich.GameObjects.Components;
#endif

namespace TwoDExampleProject
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Perovich.GameObjects.ObjectGame
    {
        
        GameObject obj1, obj2, obj3, obj4, obj5;
        TextLabel txt1, txt2;
        Button but1;



        Explosion exp;
        SmokeRing ring;
        SmokePlume plume;

        FpsCounter Counter;


        public Game1()
        {
            Content.RootDirectory = "Content";

            #if WINDOWS_PHONE
            // Frame rate is 30 fps by default for Windows Phone.
            TargetElapsedTime = TimeSpan.FromTicks(333333);

            // Extend battery life under lock.
            InactiveSleepTime = TimeSpan.FromSeconds(1);
            #else
            TargetElapsedTime = TimeSpan.FromTicks(333333 / 2);
            #endif

            obj1 = new GameObject("1",this);
            obj1.Click += new EventHandler<EventArgs>(obj1_Clicked);
            obj2 = new GameObject("2", this);
            obj2.Click += new EventHandler<EventArgs>(obj2_Clicked);
            obj3 = new GameObject("3", this);
            obj3.Click += new EventHandler<EventArgs>(obj3_Clicked);
            obj4 = new GameObject("4", this);
            obj4.Click += new EventHandler<EventArgs>(obj4_Clicked);
            obj5 = new GameObject("5", this);
            obj5.Click += new EventHandler<EventArgs>(obj5_Clicked);

            obj1.AddCollisionTargets((IEntity)obj2, obj3, obj4, obj5);
            obj2.AddCollisionTargets((IEntity)obj3, obj4, obj5);    
            obj3.AddCollisionTargets((IEntity)obj4, obj5);
            obj4.AddCollisionTargets((IEntity)obj5);


            obj1.Collided += new EventHandler<CollisionEventArgs>(Collision);
            obj2.Collided += new EventHandler<CollisionEventArgs>(Collision);
            obj3.Collided += new EventHandler<CollisionEventArgs>(Collision);
            obj4.Collided += new EventHandler<CollisionEventArgs>(Collision);
            obj5.Collided += new EventHandler<CollisionEventArgs>(Collision);
            txt1 = new TextLabel(this);
            txt2 = new TextLabel(this);

            but1 = new Button(this);
            but1.Clicked += new EventHandler(but1_Clicked);

            #if WINDOWS_PHONE
            (Graphics as GraphicsDeviceManager).SupportedOrientations = DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight | DisplayOrientation.Portrait;
            #elif WINDOWS
            (Graphics as GraphicsDeviceManager).PreferredBackBufferHeight = 800;
            (Graphics as GraphicsDeviceManager).PreferredBackBufferWidth = 480;
            this.IsMouseVisible = true;
            #endif




            KeyboardHelper.Initialize(this);
            KeyboardHelper.AddCallback(Keys.Enter, KBEnterCallback);

            exp = new Explosion(this, 1);
            ring = new SmokeRing(this, 2);
            plume = new SmokePlume(this, 9);

            Counter = new FpsCounter(this);


            IEntity entity = EntityFactory.Create<Entity>("Test Entity", this, new Velocity2D(), new Perovich.GameObjects.Components.Texture());
            entity.Find<Perovich.GameObjects.Components.Texture>().Name = "PhoneGameThumb";

            entity.Find<Position2D>().Position = new Vector2(10, 10);
            entity.Find<Velocity2D>().Velocity = new Vector2(50, 50);

        }

        void KBEnterCallback(Keys k, KeyState ks)
        {
            if (ks == KeyState.Down)
                txt2.Text = "Enter is down.";
            else if (ks == KeyState.Up)
                txt2.Text = "Enter is up.";
        }


        void but1_Clicked(object sender, EventArgs e)
        {
            Vector2 where = Vector2.Zero;
            // create the explosion at some random point on the screen.
            where.X = Perovich.GameObjects.ComponentsExtensions.RandomBetween(0, Graphics.GraphicsDevice.Viewport.Width);
            where.Y = Perovich.GameObjects.ComponentsExtensions.RandomBetween(0, Graphics.GraphicsDevice.Viewport.Height);

            exp.AddParticles(where);
            ring.AddParticles(where);
        }

        void obj5_Clicked(object sender, EventArgs e)
        {
            System.Windows.MessageBox.Show("obj5 got clicked");
        }

        void obj4_Clicked(object sender, EventArgs e)
        {
            System.Windows.MessageBox.Show("obj4 got clicked");
        }

        void obj3_Clicked(object sender, EventArgs e)
        {
            System.Windows.MessageBox.Show("obj3 got clicked");
        }

        void Collision(object sender, CollisionEventArgs e)
        {
            GameObject me = sender as GameObject;
            GameObject them = e.Other as GameObject;
            if (them == null) return;
            txt1.Text = "Collision";
            if (Math.Abs(me.Position.X - them.Position.X) > Math.Abs(me.Position.Y - them.Position.Y))
            {
                if (me.Position.X < them.Position.X)
                {
                    if (me.Velocity.X > 0)
                        me.Velocity = new Vector2(-me.Velocity.X, me.Velocity.Y);
                    if (them.Velocity.X < 0)
                        them.Velocity = new Vector2(-them.Velocity.X, them.Velocity.Y);
                }
                else if (me.Position.X > them.Position.X)
                {
                    if (me.Velocity.X < 0)
                        me.Velocity = new Vector2(-me.Velocity.X, me.Velocity.Y);
                    if (them.Velocity.X > 0)
                        them.Velocity = new Vector2(-them.Velocity.X, them.Velocity.Y);
                }
            }
            else if (Math.Abs(me.Position.X - them.Position.X) < Math.Abs(me.Position.Y - them.Position.Y))
            {
                if (me.Position.Y < them.Position.Y)
                {
                    if (me.Velocity.Y > 0)
                        me.Velocity = new Vector2(me.Velocity.X, -me.Velocity.Y);
                    if (them.Velocity.Y < 0)
                        them.Velocity = new Vector2(them.Velocity.X, -them.Velocity.Y);
                }
                else if (me.Position.Y > them.Position.Y)
                {
                    if (me.Velocity.Y < 0)
                        me.Velocity = new Vector2(me.Velocity.X, -me.Velocity.Y);
                    if (them.Velocity.Y > 0)
                        them.Velocity = new Vector2(them.Velocity.X, -them.Velocity.Y);
                }
            }
            else
            {
                if (me.Position.X < them.Position.X)
                {
                    if (me.Velocity.X > 0)
                        me.Velocity = new Vector2(-me.Velocity.X, me.Velocity.Y);
                    if (them.Velocity.X < 0)
                        them.Velocity = new Vector2(-them.Velocity.X, them.Velocity.Y);
                }
                else if (me.Position.X > them.Position.X)
                {
                    if (me.Velocity.X < 0)
                        me.Velocity = new Vector2(-me.Velocity.X, me.Velocity.Y);
                    if (them.Velocity.X > 0)
                        them.Velocity = new Vector2(-them.Velocity.X, them.Velocity.Y);
                }
                if (me.Position.Y < them.Position.Y)
                {
                    if (me.Velocity.Y > 0)
                        me.Velocity = new Vector2(me.Velocity.X, -me.Velocity.Y);
                    if (them.Velocity.Y < 0)
                        them.Velocity = new Vector2(them.Velocity.X, -them.Velocity.Y);
                }
                else if (me.Position.Y > them.Position.Y)
                {
                    if (me.Velocity.Y < 0)
                        me.Velocity = new Vector2(me.Velocity.X, -me.Velocity.Y);
                    if (them.Velocity.Y > 0)
                        them.Velocity = new Vector2(them.Velocity.X, -them.Velocity.Y);
                }
            }
        }

        void obj2_Clicked(object sender, EventArgs e)
        {
            System.Windows.MessageBox.Show("obj2 got clicked");
        }

        void obj1_Clicked(object sender, EventArgs e)
        {
            System.Windows.MessageBox.Show("obj1 got clicked");
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            

            obj1.Texture = "PhoneGameThumb";
            obj1.Size = new System.Drawing.Size(62, 62);
            obj2.Texture = "obj2tex";
            obj2.Size = new System.Drawing.Size(62, 62);
            obj3.Texture = "PhoneGameThumb";
            obj3.Size = new System.Drawing.Size(62, 62);
            obj4.Texture = "obj2tex";
            obj4.Size = new System.Drawing.Size(62, 62);
            obj5.Texture = "PhoneGameThumb";
            obj5.Size = new System.Drawing.Size(62, 62);

            obj1.Scale = 0.5f;
            obj2.Scale = 0.5f;
            obj3.Scale = 0.5f;
            obj4.Scale = 1f;
            obj5.Scale = 1f;

            obj1.Position = Vector2.Zero;
            obj1.Velocity = new Vector2(100.0f);
            obj1.BoundingStyle = BoundingStyle.Bounce;
            obj1.Enabled = true;
            obj1.Visible = true;


            obj2.Position = new Vector2(300.0f,0.0f);
            obj2.Velocity = new Vector2(-100.0f);
            obj2.BoundingStyle = BoundingStyle.Bounce;
            obj2.Enabled = true;
            obj2.Visible = true;

            obj3.Position = new Vector2(300.0f, 300.0f);
            obj3.Velocity = new Vector2(-100.0f);
            obj3.BoundingStyle = BoundingStyle.Bounce;
            obj3.Enabled = true;
            obj3.Visible = true;

            obj4.Position = new Vector2(300.0f, 600.0f);
            obj4.Velocity = new Vector2(-100.0f);
            obj4.BoundingStyle = BoundingStyle.Bounce;
            obj4.Enabled = true;
            obj4.Visible = true;

            obj5.Position = new Vector2(0.0f, 600.0f);
            obj5.Velocity = new Vector2(-100.0f);
            obj5.BoundingStyle = BoundingStyle.Bounce;
            obj5.Enabled = true;
            obj5.Visible = true;


            txt2.Position = new Vector2(0, 103);

            but1.Text = "Boom!!!";
            but1.Position = new Vector2(0, 40);
            but1.Active = true;
            but1.GeneratesMouseClicks = true;





            exp.Depth = 0;
            ring.Depth = 0.1f;



            Counter.Position = new Vector2(Graphics.GraphicsDevice.Viewport.Width, 0);
            Counter.HorizontalAlignment = HorizontalAlignment.Right;
            Counter.ForegroundColor = Color.Black;

            BackgroundColor = Color.CornflowerBlue;
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            var b = new Bounds(GraphicsDevice.Viewport.Width, 0, 0, GraphicsDevice.Viewport.Height);
            obj1.Bounds = b;
            obj2.Bounds = b;
            obj3.Bounds = b;
            obj4.Bounds = b;
            obj5.Bounds = b;

            txt1.Font = Content.Load<SpriteFont>("SpriteFont1");

            txt2.Font = Content.Load<SpriteFont>("SpriteFont1");

            but1.Font = Content.Load<SpriteFont>("SpriteFont1");
            but1.ForegroundColor = Color.Black;
            but1.BackgroundColor = Color.Blue;
            but1.BorderColor = Color.Red;
            but1.Margin = new Thickness(10.0);
            but1.Border = new Thickness(10.0);




            // TODO: use this.Content to load your game content here
            base.LoadContent();
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here
            txt1.Text = "No Collision";
            base.Update(gameTime);
            //Orange.GameObjects.Components.ComponentsExtensions.CheckColisions(this);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {

            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}
